package com.plian.system.service.im.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.bean.im.BaseInvestmentPlanImportExcelBean;
import com.plian.system.bean.im.FixedInvestmentPlanImportExcelBean;
import com.plian.system.bean.im.StakeInvestmentPlanImportExcelBean;
import com.plian.system.cache.UserCache;
import com.plian.system.common.status.CheckStatus;
import com.plian.system.constant.baseinfo.ValueSetConstant;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.constant.yth.YthConstant;
import com.plian.system.dao.sys.orgzation.OrgzationDao;
import com.plian.system.dto.im.BaseInvestmentPlanDTO;
import com.plian.system.entity.im.BaseInvestmentPlan;
import com.plian.system.entity.im.FixedInvestmentPlan;
import com.plian.system.entity.im.ProjectInfo;
import com.plian.system.entity.im.StakeInvestmentPlan;
import com.plian.system.entity.pm.propertyinformation.PropertyTime;
import com.plian.system.entity.sys.ApprovalMessage;
import com.plian.system.enumeratea.CheckName;
import com.plian.system.excel.ImportExcelUtil;
import com.plian.system.excel.ImportResult;
import com.plian.system.mapper.im.BaseInvestmentPlanMapper;
import com.plian.system.mapper.im.FixedInvestmentPlanMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.R;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.service.bt.baseinfo.BaseInfoService;
import com.plian.system.service.im.IBaseInvestmentPlanService;
import com.plian.system.service.im.IFixedInvestmentPlanService;
import com.plian.system.service.im.IProjectInfoService;
import com.plian.system.service.im.IStakeInvestmentPlanService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.file.FileService;
import com.plian.system.service.sys.message.IApprovalMessageService;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.im.*;
import com.plian.system.vo.report.ChartsVO;
import com.plian.system.vo.report.LegendVO;
import com.plian.system.vo.report.SeriesVO;
import com.plian.system.vo.report.XAxisVO;
import com.plian.system.vo.yth.YthResult;
import com.plian.system.wrapper.im.BaseInvestmentPlanWrapper;
import com.plian.system.wrapper.im.FixedInvestmentPlanWrapper;
import com.plian.system.wrapper.im.StakeInvestmentPlanWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.env.Environment;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

import static com.plian.system.constant.sys.ApprovalMessageTypeConstant.INVESTMENT_PLAN;
import static com.plian.system.constant.sys.ApprovalMessageTypeConstant.KT_TYPE;
import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * 服务实现类
 *
 * @author
 * @since 2019-09-27
 */
@Slf4j
@Service
@AllArgsConstructor
public class BaseInvestmentPlanServiceImpl extends BaseServiceImpl<BaseInvestmentPlanMapper, BaseInvestmentPlan> implements IBaseInvestmentPlanService, BaseFlowService {

	private FormWorkflowService formWorkflowService;

	private IFixedInvestmentPlanService fixedInvestmentPlanService;

	private IStakeInvestmentPlanService stakeInvestmentPlanService;

	private Environment environment;

	private IFormCodeService formCodeService;

	private OrgzationDao orgzationDao;

	private BaseInfoService baseInfoService;

	private IProjectInfoService projectInfoService;

	private FixedInvestmentPlanMapper fixedInvestmentPlanMapper;

	private BaseInvestmentPlanWrapper baseInvestmentPlanWrapper;

	private FixedInvestmentPlanWrapper fixedInvestmentPlanWrapper;

	private StakeInvestmentPlanWrapper stakeInvestmentPlanWrapper;

	private static Map<String, String> fileNameMap = new HashMap<>();

	private IApprovalMessageService approvalMessageService;

	private FileService fileService;

	private IOrgService orgService;
	@Override
	public boolean saveOrUpdate(BaseInvestmentPlan baseInvestmentPlan) {
		boolean flag = false;
		if (!Optional.ofNullable(baseInvestmentPlan.getStatus()).isPresent()) {
			baseInvestmentPlan.setStatus(UNREVIEWED);
		}
		if (!Optional.ofNullable(baseInvestmentPlan.getId()).isPresent()) {
			flag = true;
			baseInvestmentPlan.setCode(formCodeService.getCode(FormTypeConstant.IM_BASE_INVESTMENT_PLAN_FORM));
			baseInvestmentPlan.setFormType(String.valueOf(FormTypeConstant.IM_BASE_INVESTMENT_PLAN_FORM));
		}
		boolean result = super.saveOrUpdate(baseInvestmentPlan);
		if (flag){
			fileService.saveAll(String.valueOf(baseInvestmentPlan.getId()), baseInvestmentPlan.getDocList());
		}else {
			fileService.edit(String.valueOf(baseInvestmentPlan.getId()), baseInvestmentPlan.getDocList());
		}
		return result;
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public boolean deleteLogic(List<Long> ids) {
		for (Long id : ids) {
			BaseInvestmentPlan baseInvestmentPlan = getById(id);
			if (baseInvestmentPlan == null) {
				return false;
			} else if (baseInvestmentPlan.getStatus() != null &&
					(baseInvestmentPlan.getStatus() != FormStatusConstant.STASH && baseInvestmentPlan.getStatus() != UNREVIEWED)) {
				return false;
			}
			formWorkflowService.deleteProcessInstance(String.valueOf(id));
		}

		boolean result = super.deleteLogic(ids);
		if (result){
			fixedInvestmentPlanService.deleteByParentId(ids);
			stakeInvestmentPlanService.deleteByParentId(ids);
		}
		return result;
	}

	@Override
	public HashMap<String,Object> commit(String id) {
		handleStatus(Long.valueOf(id), FormStatusConstant.FLOW, null);

		//将需要提交的流程变量返回，用于工作流侧
		return new HashMap<String,Object>();
	}

	@Override
	public Boolean finish(String id) {
		return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH, "审批通过");
	}

	@Override
	public Boolean reject(String id, int formState, String comment) {
		return handleStatus(Long.valueOf(id), formState, comment);
	}


	/**
	 * 统一处理状态机事件方法
	 *
	 * @param id          主键
	 * @param updateStatus  更新状态
	 * @return boolean
	 */
	private Boolean handleStatus(Long id, int updateStatus, String comment) {
		try {
			BaseInvestmentPlan baseInvestmentPlan = getById(id);
			/**
			 * 设置审批人和审批时间
			 */
			if (updateStatus == FormStatusConstant.FINISH){
				baseInvestmentPlan.setApprovedUser(TokenUtil.getTokenUserId());
				Date now = DateUtil.now();
				baseInvestmentPlan.setApprovedTime(now);
			}

			if (StringUtil.isNotBlank(baseInvestmentPlan.getDataSource()) &&
					StringUtil.isNotBlank(baseInvestmentPlan.getDataSourceId())){
				if (updateStatus == FormStatusConstant.FINISH || updateStatus == FormStatusConstant.REJECT){
					ApprovalMessage approvalMessage = new ApprovalMessage();
					approvalMessage.setDataSourceId(baseInvestmentPlan.getDataSourceId());
					approvalMessage.setType(INVESTMENT_PLAN);
					approvalMessage.setOpinion(comment);
					approvalMessage.setIsApprove(updateStatus == FormStatusConstant.FINISH ? 2 : 1);
					approvalMessage.setIsSend(1);
					approvalMessage.setDataSourceType(KT_TYPE);
					approvalMessage.setFilingCode(baseInvestmentPlan.getCode());
					if (baseInvestmentPlan.getDataSource().equals(YthConstant.DATA_NINGBO)) {
						approvalMessage.setDataSourceType(YthConstant.DATA_NINGBO);
						approvalMessage.setFilingUserName(UserCache.userIdToName(TokenUtil.getTokenUserId()));
						approvalMessage.setFormType(FormTypeConstant.IM_BASE_INVESTMENT_PLAN_FORM);
					}
					approvalMessageService.save(approvalMessage);
				}
			}
			baseInvestmentPlan.setStatus(updateStatus);
			updateById(baseInvestmentPlan);
			return true;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
			return false;
		}
	}


	@Override
	public String checkYear(BaseInvestmentPlan baseInvestmentPlan) {
		if (!Optional.ofNullable(baseInvestmentPlan.getFilingYear()).isPresent()) {
			return "填报时间为空";
		}
		if (!Optional.ofNullable(baseInvestmentPlan.getFilingUnitId()).isPresent()){
			return "填报单位为空";
		}
		LambdaQueryWrapper<BaseInvestmentPlan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BaseInvestmentPlan::getFilingUnitId,baseInvestmentPlan.getFilingUnitId());
		queryWrapper.eq(BaseInvestmentPlan::getFilingYear, baseInvestmentPlan.getFilingYear());
		queryWrapper.eq(BaseInvestmentPlan::getFilingDate, baseInvestmentPlan.getFilingDate());
		BaseInvestmentPlan one = getOne(queryWrapper);
		if (!Optional.ofNullable(one).isPresent()){
			return null;
		}
		if (one.getId().equals(baseInvestmentPlan.getId())){
			return null;
		}
		return "该日期已填报";
	}

	@Override
	public List<PageData> findByIds(List<String> formIds) {
		LambdaQueryWrapper<BaseInvestmentPlan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.in(BaseInvestmentPlan::getId, Func.toLongList(StringUtils.join(formIds, StringPool.COMMA)));
		List<BaseInvestmentPlan> baseInvestmentPlans = list(queryWrapper);
		List<BaseInvestmentPlanVO> baseInvestmentPlanVOS= baseInvestmentPlanWrapper.entityToVO(baseInvestmentPlans);
		List<PageData> pageDataList = new ArrayList<>();
		try{
			if (CollectionUtil.isNotEmpty(baseInvestmentPlanVOS)){
				for (BaseInvestmentPlanVO vo : baseInvestmentPlanVOS){
					PageData pd = new PageData();
					pd.put("id", vo.getId());
					pd.put("UNITNAME", vo.getFilingUnitName());
					pd.put("APPLICANTNAME", vo.getCreateUserName());
					pd.put("applicantId", vo.getCreateUser());
					pd.put("applyOrganizationId", vo.getFilingUnitId());
					pd.put("formType", FormTypeConstant.IM_BASE_INVESTMENT_PLAN_FORM);
					pd.put("orgName", vo.getFilingUnitName());
					pageDataList.add(pd);
				}
			}

			return pageDataList;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		return pageDataList;
	}

	@Override
	public List<Integer> getFormType() {
		return Arrays.asList(FormTypeConstant.IM_BASE_INVESTMENT_PLAN_FORM);
	}

	@Override
	@Transactional(rollbackFor=RuntimeException.class)
	public boolean submit(BaseInvestmentPlan baseInvestmentPlan) {
		boolean result = saveOrUpdate(baseInvestmentPlan);
		if (result){
			List<FixedInvestmentPlan> fixedInvestmentPlans = baseInvestmentPlan.getFixedInvestmentPlans();
			if (CollectionUtil.isNotEmpty(fixedInvestmentPlans)){
				for (FixedInvestmentPlan fixedInvestmentPlan : fixedInvestmentPlans){
					if (fixedInvestmentPlan.getId() != null &&
							Optional.ofNullable(fixedInvestmentPlan.getIsDeleted()).isPresent() && fixedInvestmentPlan.getIsDeleted().intValue() == 1) {
						fixedInvestmentPlanService.removeById(fixedInvestmentPlan.getId());
					}else {
						fixedInvestmentPlan.setBaseInvestmentPlanId(baseInvestmentPlan.getId());
						fixedInvestmentPlanService.saveOrUpdate(fixedInvestmentPlan);
					}
				}
			}

			List<StakeInvestmentPlan> stakeInvestmentPlans = baseInvestmentPlan.getStakeInvestmentPlans();
			if (CollectionUtil.isNotEmpty(stakeInvestmentPlans)){
				for (StakeInvestmentPlan stakeInvestmentPlan : stakeInvestmentPlans){
					if (stakeInvestmentPlan.getId() != null &&
							Optional.ofNullable(stakeInvestmentPlan.getIsDeleted()).isPresent() && stakeInvestmentPlan.getIsDeleted().intValue() == 1) {
						stakeInvestmentPlanService.removeById(stakeInvestmentPlan.getId());
					}else {
						stakeInvestmentPlan.setBaseInvestmentPlanId(baseInvestmentPlan.getId());
						stakeInvestmentPlanService.saveOrUpdate(stakeInvestmentPlan);
					}
				}
			}
		}

		return result;
	}

	@Override
	public R<BaseInvestmentPlanVO> getDetailObj(BaseInvestmentPlan baseInvestmentPlan) {
		BaseInvestmentPlanVO baseInvestmentPlanVO = null;

		if (Optional.ofNullable(baseInvestmentPlan.getId()).isPresent()){
			BaseInvestmentPlan detail = getOne(Condition.getQueryWrapper(baseInvestmentPlan));
			baseInvestmentPlanVO = baseInvestmentPlanWrapper.entityToVO(detail);
		}else {
			List<BaseInvestmentPlan> baseInvestmentPlans = list(Condition.getQueryWrapper(baseInvestmentPlan));
			if (CollectionUtil.isNotEmpty(baseInvestmentPlans)){
				List<BaseInvestmentPlan> plans = baseInvestmentPlans.stream().filter(m -> Optional.ofNullable(m.getStatus()).isPresent()
						&& m.getStatus() == 3
				).sorted(Comparator.comparing(BaseInvestmentPlan::getFilingDate).reversed()).collect(Collectors.toList());
				if (CollectionUtil.isNotEmpty(plans)){
					baseInvestmentPlanVO = baseInvestmentPlanWrapper.entityToVO(plans.get(0));
				}
			}
		}

		if(!Optional.ofNullable(baseInvestmentPlanVO).isPresent()){
//			return new R(CommonCode.FAIL);
			return  R.data(baseInvestmentPlanVO);
		}

		List<FixedInvestmentPlan> fixedInvestmentPlans = fixedInvestmentPlanService.list(new LambdaQueryWrapper<FixedInvestmentPlan>()
				.eq(FixedInvestmentPlan::getBaseInvestmentPlanId, baseInvestmentPlanVO.getId()));
		baseInvestmentPlanVO.setFixedInvestmentPlanVOS(fixedInvestmentPlanWrapper.entityToVO(fixedInvestmentPlans));


		List<StakeInvestmentPlan> stakeInvestmentPlans = stakeInvestmentPlanService.list(new LambdaQueryWrapper<StakeInvestmentPlan>()
				.eq(StakeInvestmentPlan::getBaseInvestmentPlanId, baseInvestmentPlanVO.getId()));
		baseInvestmentPlanVO.setStakeInvestmentPlanVOS(stakeInvestmentPlanWrapper.entityToVO(stakeInvestmentPlans));
		baseInvestmentPlanVO.setSummary(summaryDetail(Integer.valueOf(baseInvestmentPlanVO.getFilingYear()), stakeInvestmentPlans, fixedInvestmentPlans));

		if (Optional.ofNullable(baseInvestmentPlan.getId()).isPresent()){
			//获取投资项目调整
			getChangeDetail(baseInvestmentPlanVO);
		}

		R<BaseInvestmentPlanVO> objResult = new R<>(CommonCode.SUCCESS);
		objResult.setPageData(baseInvestmentPlanVO);
		return objResult;
	}

	/**
	 * @Author: Take-off
	 * @Description: //TODO 获取投资项目调整
	 * @Date: 5:30 PM 2023/2/7
	 * @Param: [baseInvestmentPlanVO]
	 * @return: void
	 **/
	private void getChangeDetail(BaseInvestmentPlanVO baseInvestmentPlanVO){
		//获取本年第一条
		List<BaseInvestmentPlan> baseInvestmentPlans = list(new LambdaQueryWrapper<BaseInvestmentPlan>().eq(BaseInvestmentPlan::getFilingUnitId, baseInvestmentPlanVO.getFilingUnitId())
				.eq(BaseInvestmentPlan::getFilingYear, baseInvestmentPlanVO.getFilingYear()).ne(BaseInvestmentPlan::getId,baseInvestmentPlanVO.getId()));
		if (CollectionUtil.isNotEmpty(baseInvestmentPlans)){
			baseInvestmentPlans = baseInvestmentPlans.stream().sorted(Comparator.comparing(BaseInvestmentPlan::getFilingDate).reversed()).collect(Collectors.toList());
			BaseInvestmentPlan changePlan = baseInvestmentPlans.get(0);
			List<FixedInvestmentPlan> fixedInvestmentPlans = fixedInvestmentPlanService.list(new LambdaQueryWrapper<FixedInvestmentPlan>()
						.eq(FixedInvestmentPlan::getBaseInvestmentPlanId, changePlan.getId()));
			List<FixedInvestmentPlanVO> changeFixeds = fixedInvestmentPlanWrapper.entityToVO(fixedInvestmentPlans);

			List<StakeInvestmentPlan> stakeInvestmentPlans = stakeInvestmentPlanService.list(new LambdaQueryWrapper<StakeInvestmentPlan>()
						.eq(StakeInvestmentPlan::getBaseInvestmentPlanId, changePlan.getId()));
			List<StakeInvestmentPlanVO> changeStakes = stakeInvestmentPlanWrapper.entityToVO(stakeInvestmentPlans);
			getAdjustDetail(changeFixeds,changeStakes,baseInvestmentPlanVO);
		}
	}

	/**
	 * @Author: Take-off
	 * @Description: //TODO 对比之前的数据，放入子项
	 * @Date: 5:30 PM 2023/2/7
	 * @Param: [changeFixeds, changeStakes, baseInvestmentPlanVO]
	 * @return: void
	 **/
	private void getAdjustDetail(List<FixedInvestmentPlanVO> changeFixeds ,List<StakeInvestmentPlanVO> changeStakes, BaseInvestmentPlanVO baseInvestmentPlanVO){
		//原来的子项
		List<StakeInvestmentPlanVO> stakeInvestment = baseInvestmentPlanVO.getStakeInvestmentPlanVOS();
		List<FixedInvestmentPlanVO> fixedInvestment = baseInvestmentPlanVO.getFixedInvestmentPlanVOS();

		//投资项目调整-股权投资-新增
		List<StakeInvestmentPlanAddVO> stakeInvestmentAdd = new ArrayList<>();
		//投资项目调整-股权投资-取消
		List<StakeInvestmentPlanAddVO> stakeInvestmentReduce = new ArrayList<>();
		//投资项目调整-固定资产-新增
		List<StakeInvestmentPlanAddVO> fixedInvestmentAdd = new ArrayList<>();
		//投资项目调整-固定资产-减少
		List<StakeInvestmentPlanAddVO> fixedInvestmentReduce = new ArrayList<>();

		//固定资产 - 投资对比
		if (CollectionUtil.isNotEmpty(changeFixeds) && CollectionUtil.isNotEmpty(fixedInvestment)){
			List<String> names = fixedInvestment.stream().map(FixedInvestmentPlanVO::getProjectName).filter(m -> Optional.ofNullable(m).isPresent()).collect(Collectors.toList());

			List<String> changeNames = changeFixeds.stream().map(FixedInvestmentPlanVO::getProjectName).filter(m -> Optional.ofNullable(m).isPresent()).collect(Collectors.toList());
			for (FixedInvestmentPlanVO changeFixed:changeFixeds){
				BigDecimal changeTotal = changeFixed.getPlanInvestmentTotal();
				changeTotal = Optional.ofNullable(changeTotal).isPresent() ? changeTotal : BigDecimal.ZERO;
				if (names.contains(changeFixed.getProjectName())){
					//判断 调增还是调减
					FixedInvestmentPlanVO oldFixed = fixedInvestment.stream().filter(m -> m.getProjectName().equals(changeFixed.getProjectName())).collect(Collectors.toList()).get(0);
					BigDecimal oldTotal = oldFixed.getPlanInvestmentTotal();
					oldTotal = Optional.ofNullable(oldTotal).isPresent() ? oldTotal : BigDecimal.ZERO;

					StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
					stakeInvestmentPlanAddVO.setProjectName(changeFixed.getProjectName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyName(changeFixed.getInvestmentCompanyName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(changeFixed.getInvestmentCompanyRankName());
					stakeInvestmentPlanAddVO.setPlanTotalInvestment(oldTotal);
					stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(changeTotal);

					if (oldTotal.compareTo(changeTotal) > 0){
						//调减
						stakeInvestmentPlanAddVO.setRemark("调减");
						fixedInvestmentReduce.add(stakeInvestmentPlanAddVO);
					}else if (oldTotal.compareTo(changeTotal) < 0){
						//调增
						stakeInvestmentPlanAddVO.setRemark("调增");
						fixedInvestmentAdd.add(stakeInvestmentPlanAddVO);
					}
				}else {
					//新增
					StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
					stakeInvestmentPlanAddVO.setProjectName(changeFixed.getProjectName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyName(changeFixed.getInvestmentCompanyName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(changeFixed.getInvestmentCompanyRankName());
					stakeInvestmentPlanAddVO.setPlanTotalInvestment(BigDecimal.ZERO);
					stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(changeTotal);
					stakeInvestmentPlanAddVO.setRemark("新增");
					fixedInvestmentAdd.add(stakeInvestmentPlanAddVO);
				}
			}
			//判断取消的
			for (FixedInvestmentPlanVO oldFixed:fixedInvestment){
				if (!changeNames.contains(oldFixed.getProjectName())){
					StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
					stakeInvestmentPlanAddVO.setProjectName(oldFixed.getProjectName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyName(oldFixed.getInvestmentCompanyName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(oldFixed.getInvestmentCompanyRankName());
					stakeInvestmentPlanAddVO.setPlanTotalInvestment(oldFixed.getPlanInvestmentTotal());
					stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(BigDecimal.ZERO);
					stakeInvestmentPlanAddVO.setRemark("取消");
					fixedInvestmentReduce.add(stakeInvestmentPlanAddVO);
				}
			}
		}
		if (CollectionUtil.isNotEmpty(fixedInvestment) && CollectionUtil.isEmpty(changeFixeds)){
			//全是新增的
			fixedInvestment.forEach(investment ->{
				StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
				stakeInvestmentPlanAddVO.setProjectName(investment.getProjectName());
				stakeInvestmentPlanAddVO.setInvestmentCompanyName(investment.getInvestmentCompanyName());
				stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(investment.getInvestmentCompanyRankName());
				stakeInvestmentPlanAddVO.setPlanTotalInvestment(BigDecimal.ZERO);
				stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(investment.getPlanTotalInvestment());
				stakeInvestmentPlanAddVO.setRemark("新增");
				fixedInvestmentAdd.add(stakeInvestmentPlanAddVO);
			});
		}
		if (CollectionUtil.isEmpty(fixedInvestment) && CollectionUtil.isNotEmpty(changeFixeds)){
			//全是取消的
			changeFixeds.forEach(investment ->{
				StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
				stakeInvestmentPlanAddVO.setProjectName(investment.getProjectName());
				stakeInvestmentPlanAddVO.setInvestmentCompanyName(investment.getInvestmentCompanyName());
				stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(investment.getInvestmentCompanyRankName());
				stakeInvestmentPlanAddVO.setPlanTotalInvestment(investment.getPlanTotalInvestment());
				stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(BigDecimal.ZERO);
				stakeInvestmentPlanAddVO.setRemark("取消");
				fixedInvestmentReduce.add(stakeInvestmentPlanAddVO);
			});

		}

		//股权 - 投资对比
		if (CollectionUtil.isNotEmpty(changeStakes) && CollectionUtil.isNotEmpty(stakeInvestment)){
			List<String> names = stakeInvestment.stream().map(StakeInvestmentPlanVO::getProjectName).filter(m -> Optional.ofNullable(m).isPresent()).collect(Collectors.toList());

			List<String> changeNames = changeStakes.stream().map(StakeInvestmentPlanVO::getProjectName).filter(m -> Optional.ofNullable(m).isPresent()).collect(Collectors.toList());
			for (StakeInvestmentPlanVO changeStake:changeStakes){
				BigDecimal changeTotal = changeStake.getPlanTotalInvestment();
				changeTotal = Optional.ofNullable(changeTotal).isPresent() ? changeTotal : BigDecimal.ZERO;

				if (names.contains(changeStake.getProjectName())){
					//判断 调增还是调减
					StakeInvestmentPlanVO oldStake = stakeInvestment.stream().filter(m -> m.getProjectName().equals(changeStake.getProjectName())).collect(Collectors.toList()).get(0);

					BigDecimal oldTotal = oldStake.getPlanTotalInvestment();
					oldTotal = Optional.ofNullable(oldTotal).isPresent() ? oldTotal : BigDecimal.ZERO;

					StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
					stakeInvestmentPlanAddVO.setProjectName(changeStake.getProjectName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyName(changeStake.getInvestmentCompanyName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(changeStake.getInvestmentCompanyRankName());
					stakeInvestmentPlanAddVO.setPlanTotalInvestment(oldTotal);
					stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(changeTotal);

					if (oldTotal.compareTo(changeTotal) > 0){
						//调减
						stakeInvestmentPlanAddVO.setRemark("调减");
						stakeInvestmentReduce.add(stakeInvestmentPlanAddVO);
					}else if (oldTotal.compareTo(changeTotal) < 0){
						//调增
						stakeInvestmentPlanAddVO.setRemark("调增");
						stakeInvestmentAdd.add(stakeInvestmentPlanAddVO);
					}
				}else {
					//新增
					StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
					stakeInvestmentPlanAddVO.setProjectName(changeStake.getProjectName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyName(changeStake.getInvestmentCompanyName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(changeStake.getInvestmentCompanyRankName());
					stakeInvestmentPlanAddVO.setPlanTotalInvestment(BigDecimal.ZERO);
					stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(changeStake.getPlanTotalInvestment());
					stakeInvestmentPlanAddVO.setRemark("新增");
					stakeInvestmentAdd.add(stakeInvestmentPlanAddVO);
				}
			}
			//判断取消的
			for (StakeInvestmentPlanVO oldStake:stakeInvestment){
				if (!changeNames.contains(oldStake.getProjectName())){
					StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
					stakeInvestmentPlanAddVO.setProjectName(oldStake.getProjectName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyName(oldStake.getInvestmentCompanyName());
					stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(oldStake.getInvestmentCompanyRankName());
					stakeInvestmentPlanAddVO.setPlanTotalInvestment(oldStake.getPlanTotalInvestment());
					stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(BigDecimal.ZERO);
					stakeInvestmentPlanAddVO.setRemark("取消");
					stakeInvestmentReduce.add(stakeInvestmentPlanAddVO);
				}
			}
		}
		if (CollectionUtil.isNotEmpty(stakeInvestment) && CollectionUtil.isEmpty(changeStakes)){
			//全是新增的
			stakeInvestment.forEach(oldStake ->{
				StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
				stakeInvestmentPlanAddVO.setProjectName(oldStake.getProjectName());
				stakeInvestmentPlanAddVO.setInvestmentCompanyName(oldStake.getInvestmentCompanyName());
				stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(oldStake.getInvestmentCompanyRankName());
				stakeInvestmentPlanAddVO.setPlanTotalInvestment(BigDecimal.ZERO);
				stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(oldStake.getPlanTotalInvestment());
				stakeInvestmentPlanAddVO.setRemark("新增");
				stakeInvestmentAdd.add(stakeInvestmentPlanAddVO);
			});
		}
		if (CollectionUtil.isEmpty(stakeInvestment) && CollectionUtil.isNotEmpty(changeStakes)){
			//全是取消的
			changeStakes.forEach(oldStake ->{
				StakeInvestmentPlanAddVO stakeInvestmentPlanAddVO = new StakeInvestmentPlanAddVO();
				stakeInvestmentPlanAddVO.setProjectName(oldStake.getProjectName());
				stakeInvestmentPlanAddVO.setInvestmentCompanyName(oldStake.getInvestmentCompanyName());
				stakeInvestmentPlanAddVO.setInvestmentCompanyRankName(oldStake.getInvestmentCompanyRankName());
				stakeInvestmentPlanAddVO.setPlanTotalInvestment(oldStake.getPlanTotalInvestment());
				stakeInvestmentPlanAddVO.setPlanTotalInvestmentNow(BigDecimal.ZERO);
				stakeInvestmentPlanAddVO.setRemark("取消");
				stakeInvestmentReduce.add(stakeInvestmentPlanAddVO);
			});
		}

		baseInvestmentPlanVO.setStakeInvestmentAdd(stakeInvestmentAdd);
		baseInvestmentPlanVO.setStakeInvestmentReduce(stakeInvestmentReduce);
		baseInvestmentPlanVO.setFixedInvestmentAdd(fixedInvestmentAdd);
		baseInvestmentPlanVO.setFixedInvestmentReduce(fixedInvestmentReduce);
	}

	@Override
	public List<InvestmentPlanSummaryVO> summary(String filingUnitId, String filingYear){
		LambdaQueryWrapper<BaseInvestmentPlan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BaseInvestmentPlan::getFilingUnitId, filingUnitId);
		queryWrapper.eq(BaseInvestmentPlan::getFilingYear, filingYear);
		queryWrapper.orderByDesc(BaseInvestmentPlan::getFilingDate);
		List<BaseInvestmentPlan> baseInvestmentPlans = list(queryWrapper);
		if (CollectionUtil.isEmpty(baseInvestmentPlans)){
			return new ArrayList<>();
		}

		BaseInvestmentPlan baseInvestmentPlan = baseInvestmentPlans.get(0);
		List<StakeInvestmentPlan> stakeInvestmentPlans = stakeInvestmentPlanService.list(new LambdaQueryWrapper<StakeInvestmentPlan>()
				.eq(StakeInvestmentPlan::getBaseInvestmentPlanId, baseInvestmentPlan.getId()));

		List<FixedInvestmentPlan> fixedInvestmentPlans = fixedInvestmentPlanService.list(new LambdaQueryWrapper<FixedInvestmentPlan>()
				.eq(FixedInvestmentPlan::getBaseInvestmentPlanId, baseInvestmentPlan.getId()));

		return summaryDetail(Integer.valueOf(filingYear), stakeInvestmentPlans, fixedInvestmentPlans);
	}

	private void stakeNewSwitch(StakeInvestmentPlan stakeInvestmentPlan, List<InvestmentPlanSummaryVO> results){
		switch (stakeInvestmentPlan.getProjectNatureId()){
			case "070001":
			case "070007":
				stakeNewCount(results, 9, stakeInvestmentPlan);
				break;
			case "070002":
			case "070008":
				stakeNewCount(results, 10, stakeInvestmentPlan);
				break;
			case "070003":
			case "070009":
				stakeNewCount(results, 11, stakeInvestmentPlan);
				break;
			case "070004":
			case "070010":
				stakeNewCount(results, 12, stakeInvestmentPlan);
				break;
			case "070005":
			case "070011":
				stakeNewCount(results, 13, stakeInvestmentPlan);
				break;
			case "070006":
			case "070012":
				stakeNewCount(results, 14, stakeInvestmentPlan);
				break;
			default:
				break;
		}
	}

	private void stakeOldSwitch(StakeInvestmentPlan stakeInvestmentPlan, List<InvestmentPlanSummaryVO> results){
		switch (stakeInvestmentPlan.getProjectNatureId()){
			case "070001":
			case "070007":
				stakeOldCount(results, 9, stakeInvestmentPlan);
				break;
			case "070002":
			case "070008":
				stakeOldCount(results, 10, stakeInvestmentPlan);
				break;
			case "070003":
			case "070009":
				stakeOldCount(results, 11, stakeInvestmentPlan);
				break;
			case "070004":
			case "070010":
				stakeOldCount(results, 12, stakeInvestmentPlan);
				break;
			case "070005":
			case "070011":
				stakeOldCount(results, 13, stakeInvestmentPlan);
				break;
			case "070006":
			case "070012":
				stakeOldCount(results, 14, stakeInvestmentPlan);
				break;
			default:
				break;
		}
	}

	private void stakeOtherSwitch(StakeInvestmentPlan stakeInvestmentPlan, List<InvestmentPlanSummaryVO> results){
		switch (stakeInvestmentPlan.getProjectNatureId()){
			case "070001":
			case "070007":
				stakeOtherCount(results, 9, stakeInvestmentPlan);
				break;
			case "070002":
			case "070008":
				stakeOtherCount(results, 10, stakeInvestmentPlan);
				break;
			case "070003":
			case "070009":
				stakeOtherCount(results, 11, stakeInvestmentPlan);
				break;
			case "070004":
			case "070010":
				stakeOtherCount(results, 12, stakeInvestmentPlan);
				break;
			case "070005":
			case "070011":
				stakeOtherCount(results, 13, stakeInvestmentPlan);
				break;
			case "070006":
			case "070012":
				stakeOtherCount(results, 14, stakeInvestmentPlan);
				break;
			default:
				break;
		}
	}

	private void fixedNewSwitch(FixedInvestmentPlan fixedInvestmentPlan, List<InvestmentPlanSummaryVO> results){
		switch (fixedInvestmentPlan.getProjectNatureId()){
			case "070001":
			case "070007":
				fixedNewCount(results, 9, fixedInvestmentPlan);
				break;
			case "070002":
			case "070008":
				fixedNewCount(results, 10, fixedInvestmentPlan);
				break;
			case "070003":
			case "070009":
				fixedNewCount(results, 11, fixedInvestmentPlan);
				break;
			case "070004":
			case "070010":
				fixedNewCount(results, 12, fixedInvestmentPlan);
				break;
			case "070005":
			case "070011":
				fixedNewCount(results, 13, fixedInvestmentPlan);
				break;
			case "070006":
			case "070012":
				fixedNewCount(results, 14, fixedInvestmentPlan);
				break;
			default:
				break;
		}
	}

	private void fixedOldSwitch(FixedInvestmentPlan fixedInvestmentPlan, List<InvestmentPlanSummaryVO> results){
		switch (fixedInvestmentPlan.getProjectNatureId()){
			case "070001":
			case "070007":
				fixedOldCount(results, 9, fixedInvestmentPlan);
				break;
			case "070002":
			case "070008":
				fixedOldCount(results, 10, fixedInvestmentPlan);
				break;
			case "070003":
			case "070009":
				fixedOldCount(results, 11, fixedInvestmentPlan);
				break;
			case "070004":
			case "070010":
				fixedOldCount(results, 12, fixedInvestmentPlan);
				break;
			case "070005":
			case "070011":
				fixedOldCount(results, 13, fixedInvestmentPlan);
				break;
			case "070006":
			case "070012":
				fixedOldCount(results, 14, fixedInvestmentPlan);
				break;
			default:
				break;
		}
	}

	private void fixedOtherSwitch(FixedInvestmentPlan fixedInvestmentPlan, List<InvestmentPlanSummaryVO> results){
		switch (fixedInvestmentPlan.getProjectNatureId()){
			case "070001":
			case "070007":
				fixedOtherCount(results, 9, fixedInvestmentPlan);
				break;
			case "070002":
			case "070008":
				fixedOtherCount(results, 10, fixedInvestmentPlan);
				break;
			case "070003":
			case "070009":
				fixedOtherCount(results, 11, fixedInvestmentPlan);
				break;
			case "070004":
			case "070010":
				fixedOtherCount(results, 12, fixedInvestmentPlan);
				break;
			case "070005":
			case "070011":
				fixedOtherCount(results, 13, fixedInvestmentPlan);
				break;
			case "070006":
			case "070012":
				fixedOtherCount(results, 14, fixedInvestmentPlan);
				break;
			default:
				break;
		}
	}
	private List<InvestmentPlanSummaryVO> summaryDetail(int year, List<StakeInvestmentPlan> stakeInvestmentPlans, List<FixedInvestmentPlan> fixedInvestmentPlans) {
		List<InvestmentPlanSummaryVO> results = initSummary(year);

		if (CollectionUtil.isNotEmpty(stakeInvestmentPlans)){
			for (StakeInvestmentPlan stakeInvestmentPlan : stakeInvestmentPlans){
				/**
				 * 1 股权投资 2 固定资产投资 5 自营项目 6 政府性项目  9、10、11、12、13、14 分类三
				 */
				if (stakeInvestmentPlan.getIsNewProject() == 2){
					stakeNewCount(results, 1, stakeInvestmentPlan);

					if (stakeInvestmentPlan.getProjectCategory() == 4){
						stakeNewCount(results, 6, stakeInvestmentPlan);
					}else {
						stakeNewCount(results, 5, stakeInvestmentPlan);
					}
					stakeNewSwitch(stakeInvestmentPlan, results);
				}else {
					stakeOldCount(results, 1, stakeInvestmentPlan);

					if (stakeInvestmentPlan.getProjectCategory() == 4){
						stakeOldCount(results, 6, stakeInvestmentPlan);
					}else {
						stakeOldCount(results, 5, stakeInvestmentPlan);
					}

					stakeOldSwitch(stakeInvestmentPlan, results);
				}

				stakeOtherCount(results, 1, stakeInvestmentPlan);

				if (stakeInvestmentPlan.getProjectCategory() == 4){
					stakeOtherCount(results, 6, stakeInvestmentPlan);
				}else {
					stakeOtherCount(results, 5, stakeInvestmentPlan);
				}

				stakeOtherSwitch(stakeInvestmentPlan, results);

			}

		}

		if (CollectionUtil.isNotEmpty(fixedInvestmentPlans)){
			for (FixedInvestmentPlan fixedInvestmentPlan : fixedInvestmentPlans){
				if (Optional.ofNullable(fixedInvestmentPlan.getIsNewProject()).isPresent()){
					/**
					 * 2 固定资产投资
					 */
					if (fixedInvestmentPlan.getIsNewProject() == 2){
						fixedNewCount(results, 2, fixedInvestmentPlan);

						if (fixedInvestmentPlan.getProjectCategory() == 4){
							fixedNewCount(results, 6, fixedInvestmentPlan);
						}else {
							fixedNewCount(results, 5, fixedInvestmentPlan);
						}

						fixedNewSwitch(fixedInvestmentPlan, results);
					}else {
						fixedOldCount(results, 2, fixedInvestmentPlan);

						if (fixedInvestmentPlan.getProjectCategory() == 4){
							fixedOldCount(results, 6, fixedInvestmentPlan);
						}else {
							fixedOldCount(results, 5, fixedInvestmentPlan);
						}
						fixedOldSwitch(fixedInvestmentPlan, results);
					}
				}

				fixedOtherCount(results, 2, fixedInvestmentPlan);

				if (Optional.ofNullable(fixedInvestmentPlan.getProjectCategory()).isPresent()){
					if (fixedInvestmentPlan.getProjectCategory() == 4) {
						fixedOtherCount(results, 6, fixedInvestmentPlan);
					}else {
						fixedOtherCount(results, 5, fixedInvestmentPlan);
					}
				}
				fixedOtherSwitch(fixedInvestmentPlan, results);
			}
		}

		/**
		 * 分类一 合计 3 = 1+2
		 * 分类二 合计 7 = 5+6
		 * 分类三 合计 15 = 9+10+11+12+13+14
		 */
		List<InvestmentPlanSummaryVO> oneList = new ArrayList<>();
		oneList.add(results.get(1));
		oneList.add(results.get(2));
		total(results.get(3), oneList);

		List<InvestmentPlanSummaryVO> twoList = new ArrayList<>();
		twoList.add(results.get(5));
		twoList.add(results.get(6));
		total(results.get(7), twoList);

		List<InvestmentPlanSummaryVO> threeList = new ArrayList<>();
		threeList.add(results.get(9));
		threeList.add(results.get(10));
		threeList.add(results.get(11));
		threeList.add(results.get(12));
		threeList.add(results.get(13));
		threeList.add(results.get(14));
		total(results.get(15), threeList);

		/**
		 * 计算 本年度投资汇总 项目平均内部收益率、负面清单内项目投资占比、占总投资额比例
		 */
		for (int i = 0; i < results.size(); i++){
			if (!(i == 0 || i == 4 || i == 8)){
				results.get(i).setYearInvestment(BigDecimalUtil.add(results.get(i).getNewInvestmentPlan(), results.get(i).getOldYearInvestment()));
				int number = results.get(i).getNewNumber() + results.get(i).getOldNumber();
				if (number != 0){
					results.get(i).setAverageIrr(BigDecimalUtil.divide(results.get(i).getTotalIrr(), new BigDecimal(number),
							2, BigDecimal.ROUND_HALF_UP));
				}

				results.get(i).setNegativeDuty(BigDecimalUtil.divide(results.get(i).getNegativeInvestment(), results.get(i).getYearInvestment(),
						2, BigDecimal.ROUND_HALF_UP, 100));

				results.get(i).setOldCompleteInvestmentDuty(BigDecimalUtil.divide(results.get(i).getOldCompleteInvestment(), results.get(i).getOldTotalInvestment(),
						2, BigDecimal.ROUND_HALF_UP, 100));
			}
		}

		return results;
	}

	@Override
	public String checkSummary(BaseInvestmentPlan baseInvestmentPlan) {
		if (StringUtil.isBlank(baseInvestmentPlan.getFilingUnitId())){
			return "填报单位不能为空";
		}
		if (StringUtil.isBlank(baseInvestmentPlan.getFilingYear())){
			return "填报年度不能为空";
		}
		return null;
	}

	@Override
	public List<InvestmentUnitSummaryVO> unitSummary(BaseInvestmentPlanDTO baseInvestmentPlanDTO) {
		/**
		 * 填报年年度为空时默认为当前年度
		 */
		if (StringUtil.isBlank(baseInvestmentPlanDTO.getFilingYear())){
			baseInvestmentPlanDTO.setFilingYear(DateUtil.format(DateUtil.now(), DateUtil.PATTERN_YEAR));
		}
		List<InvestmentUnitSummaryVO> summaryVOS = baseMapper.unitSummary(baseInvestmentPlanDTO.getFilingYear(), baseInvestmentPlanDTO.getFillingUnitIds());
		InvestmentUnitSummaryVO end = InvestmentUnitSummaryVO.builder().filingUnitName("合计")
				.newProjectNumber(0).oldProjectNumber(0).zyProjectNumber(0).zfProjectNumber(0)
				.build();

		if (CollectionUtil.isNotEmpty(summaryVOS)){
			for (InvestmentUnitSummaryVO vo : summaryVOS){
				end.setInvestment(BigDecimalUtil.add(end.getInvestment(), vo.getInvestment()));
				end.setFixedInvestment(BigDecimalUtil.add(end.getFixedInvestment(), vo.getFixedInvestment()));
				end.setStakeInvestment(BigDecimalUtil.add(end.getStakeInvestment(), vo.getStakeInvestment()));
				end.setNewProjectNumber(BigDecimalUtil.integerAdd(end.getNewProjectNumber(), vo.getNewProjectNumber()));
				end.setNewInvestment(BigDecimalUtil.add(end.getNewInvestment(), vo.getNewInvestment()));
				end.setOldProjectNumber(BigDecimalUtil.integerAdd(end.getOldProjectNumber(), vo.getOldProjectNumber()));
				end.setOldInvestment(BigDecimalUtil.add(end.getOldInvestment(), vo.getOldInvestment()));
				end.setZyProjectNumber(BigDecimalUtil.integerAdd(end.getZyProjectNumber(), vo.getZyProjectNumber()));
				end.setZyInvestment(BigDecimalUtil.add(end.getZyInvestment(), vo.getZyInvestment()));
				end.setZfProjectNumber(BigDecimalUtil.integerAdd(end.getZfProjectNumber(), vo.getZfProjectNumber()));
				end.setZfInvestment(BigDecimalUtil.add(end.getZfInvestment(), vo.getZfInvestment()));

			}
			summaryVOS.add(end);
		}

		return summaryVOS;
	}

	private void total(InvestmentPlanSummaryVO total, List<InvestmentPlanSummaryVO> list){
		for (InvestmentPlanSummaryVO vo : list){
			total.setNewNumber(total.getNewNumber() + vo.getNewNumber());
			total.setNewTotalInvestment(BigDecimalUtil.add(total.getNewTotalInvestment(), vo.getNewTotalInvestment()));
			total.setNewCapital(BigDecimalUtil.add(total.getNewCapital(), vo.getNewCapital()));
			total.setNewInvestmentPlan(BigDecimalUtil.add(total.getNewInvestmentPlan(), vo.getNewInvestmentPlan()));

			total.setOldNumber(total.getOldNumber() + vo.getOldNumber());
			total.setOldTotalInvestment(BigDecimalUtil.add(total.getOldTotalInvestment(), vo.getOldTotalInvestment()));
			total.setOldCapital(BigDecimalUtil.add(total.getOldCapital(), vo.getOldCapital()));
			total.setOldCompleteInvestment(BigDecimalUtil.add(total.getOldCompleteInvestment(), vo.getOldCompleteInvestment()));
			total.setOldYearInvestment(BigDecimalUtil.add(total.getOldYearInvestment(), vo.getOldYearInvestment()));

			total.setMainProjectNumber(total.getMainProjectNumber() + vo.getMainProjectNumber());
			total.setCultivateProjectNumber(total.getCultivateProjectNumber() + vo.getCultivateProjectNumber());
			total.setNoncoreProjectNumber(total.getNoncoreProjectNumber() + vo.getNoncoreProjectNumber());
			total.setTotalIrr(BigDecimalUtil.add(total.getTotalIrr(), vo.getTotalIrr()));
			total.setNegativeInvestment(BigDecimalUtil.add(total.getNegativeInvestment(), vo.getNegativeInvestment()));

		}
	}

	private void stakeNewCount(List<InvestmentPlanSummaryVO> results, int index, StakeInvestmentPlan stakeInvestmentPlan){
		results.get(index).setNewNumber(results.get(index).getNewNumber() + 1);
		results.get(index).setNewTotalInvestment(BigDecimalUtil.add(results.get(index).getNewTotalInvestment(), stakeInvestmentPlan.getPlanTotalInvestment()));
		results.get(index).setNewCapital(BigDecimalUtil.add(results.get(index).getNewCapital(), stakeInvestmentPlan.getCapital()));
		results.get(index).setNewInvestmentPlan(BigDecimalUtil.add(results.get(index).getNewInvestmentPlan(), stakeInvestmentPlan.getPlanCompleteInvestment()));
	}

	private void stakeOldCount(List<InvestmentPlanSummaryVO> results, int index, StakeInvestmentPlan stakeInvestmentPlan){
		results.get(index).setOldNumber(results.get(index).getOldNumber() + 1);
		results.get(index).setOldTotalInvestment(BigDecimalUtil.add(results.get(index).getOldTotalInvestment(), stakeInvestmentPlan.getPlanTotalInvestment()));
		results.get(index).setOldCapital(BigDecimalUtil.add(results.get(index).getOldCapital(), stakeInvestmentPlan.getCapital()));
		results.get(index).setOldCompleteInvestment(BigDecimalUtil.add(results.get(index).getOldCompleteInvestment(),
				BigDecimalUtil.subtract(stakeInvestmentPlan.getPlanCompleteInvestmentTotal(), stakeInvestmentPlan.getPlanCompleteInvestment())));
		//占总投资额比例最后算
		results.get(index).setOldYearInvestment(BigDecimalUtil.add(results.get(index).getOldYearInvestment(), stakeInvestmentPlan.getPlanCompleteInvestment()));
	}

	private void stakeOtherCount(List<InvestmentPlanSummaryVO> results, int index, StakeInvestmentPlan stakeInvestmentPlan) {
		if (stakeInvestmentPlan.getProjectCategory() == 1 || stakeInvestmentPlan.getProjectCategory() == 4){
			results.get(index).setMainProjectNumber(results.get(index).getMainProjectNumber() + 1);
		}

		if (stakeInvestmentPlan.getProjectCategory() == 2){
			results.get(index).setCultivateProjectNumber(results.get(index).getCultivateProjectNumber() + 1);
		}

		if (stakeInvestmentPlan.getProjectCategory() == 3){
			results.get(index).setNoncoreProjectNumber(results.get(index).getNoncoreProjectNumber() + 1);
		}
		results.get(index).setTotalIrr(BigDecimalUtil.add(results.get(index).getTotalIrr(), stakeInvestmentPlan.getPlanTotalInvestmentIrr()));

		if (stakeInvestmentPlan.getIsNegativeProject() != null && stakeInvestmentPlan.getIsNegativeProject() == 2){
			results.get(index).setNegativeInvestment(BigDecimalUtil.add(results.get(index).getNegativeInvestment(), stakeInvestmentPlan.getPlanCompleteInvestment()));
		}
	}

	private void fixedNewCount(List<InvestmentPlanSummaryVO> results, int index, FixedInvestmentPlan fixedInvestmentPlan){
		results.get(index).setNewNumber(results.get(index).getNewNumber() + 1);
		results.get(index).setNewTotalInvestment(BigDecimalUtil.add(results.get(index).getNewTotalInvestment(), fixedInvestmentPlan.getPlanTotalInvestment()));
		results.get(index).setNewCapital(BigDecimalUtil.add(results.get(index).getNewCapital(), fixedInvestmentPlan.getCapital()));
		results.get(index).setNewInvestmentPlan(BigDecimalUtil.add(results.get(index).getNewInvestmentPlan(), fixedInvestmentPlan.getPlanInvestmentTotal()));
	}

	private void fixedOldCount(List<InvestmentPlanSummaryVO> results, int index, FixedInvestmentPlan fixedInvestmentPlan){
		results.get(index).setOldNumber(results.get(index).getOldNumber() + 1);
		results.get(index).setOldTotalInvestment(BigDecimalUtil.add(results.get(index).getOldTotalInvestment(), fixedInvestmentPlan.getPlanTotalInvestment()));
		results.get(index).setOldCapital(BigDecimalUtil.add(results.get(index).getOldCapital(), fixedInvestmentPlan.getCapital()));
		results.get(index).setOldCompleteInvestment(BigDecimalUtil.add(results.get(index).getOldCompleteInvestment(), fixedInvestmentPlan.getCompleteInvestmentLastYear()));
		results.get(index).setOldYearInvestment(BigDecimalUtil.add(results.get(index).getOldYearInvestment(), fixedInvestmentPlan.getPlanInvestmentTotal()));
	}

	private void fixedOtherCount(List<InvestmentPlanSummaryVO> results, int index, FixedInvestmentPlan fixedInvestmentPlan){
		if (fixedInvestmentPlan.getProjectCategory() == 1 || fixedInvestmentPlan.getProjectCategory() == 4){
			results.get(index).setMainProjectNumber(results.get(index).getMainProjectNumber() + 1);
		}

		if (fixedInvestmentPlan.getProjectCategory() == 2){
			results.get(index).setCultivateProjectNumber(results.get(index).getCultivateProjectNumber() + 1);
		}

		if (fixedInvestmentPlan.getProjectCategory() == 3){
			results.get(index).setNoncoreProjectNumber(results.get(index).getNoncoreProjectNumber() + 1);
		}

		results.get(index).setTotalIrr(BigDecimalUtil.add(results.get(index).getTotalIrr(), fixedInvestmentPlan.getIrr()));

		if (fixedInvestmentPlan.getIsNegativeProject() == 2){
			results.get(index).setNegativeInvestment(BigDecimalUtil.add(results.get(index).getNegativeInvestment(), fixedInvestmentPlan.getPlanInvestmentTotal()));
		}
	}

	private List<InvestmentPlanSummaryVO> initSummary(int year){
		List<InvestmentPlanSummaryVO> init = new ArrayList<>();
		init.add(InvestmentPlanSummaryVO.builder().index("1").category("分类一").build());
		init.add(InvestmentPlanSummaryVO.builder().index("1.1").category("股权投资").newNumber(0)
				.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
				.build());
		init.add(InvestmentPlanSummaryVO.builder().index("1.2").category("固定资产投资").newNumber(0)
				.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
				.build());
		init.add(InvestmentPlanSummaryVO.builder().index("1.3").category("合计").newNumber(0)
				.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
				.build());

		init.add(InvestmentPlanSummaryVO.builder().index("2").category("分类二").build());
		init.add(InvestmentPlanSummaryVO.builder().index("2.1").category("自营项目").newNumber(0)
				.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
				.build());
		init.add(InvestmentPlanSummaryVO.builder().index("2.2").category("政府性项目").newNumber(0)
				.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
				.build());
		init.add(InvestmentPlanSummaryVO.builder().index("2.3").category("合计").newNumber(0)
				.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
				.build());

		init.add(InvestmentPlanSummaryVO.builder().index("3").category("分类三").build());
		if (year >= 2021){
			init.add(InvestmentPlanSummaryVO.builder().index("3.1").category("科技创新项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
			init.add(InvestmentPlanSummaryVO.builder().index("3.2").category("现代产业项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
			init.add(InvestmentPlanSummaryVO.builder().index("3.3").category("交通设施项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
			init.add(InvestmentPlanSummaryVO.builder().index("3.4").category("生态环保项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
			init.add(InvestmentPlanSummaryVO.builder().index("3.5").category("公共服务项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
		}else {
			init.add(InvestmentPlanSummaryVO.builder().index("3.1").category("城市基础设施项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
			init.add(InvestmentPlanSummaryVO.builder().index("3.2").category("交通建设项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
			init.add(InvestmentPlanSummaryVO.builder().index("3.3").category("重点区块开发项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
			init.add(InvestmentPlanSummaryVO.builder().index("3.4").category("公共服务项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
			init.add(InvestmentPlanSummaryVO.builder().index("3.5").category("港口物流项目").newNumber(0)
					.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
					.build());
		}

		init.add(InvestmentPlanSummaryVO.builder().index("3.6").category("其他项目").newNumber(0)
				.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
				.build());
		init.add(InvestmentPlanSummaryVO.builder().index("3.7").category("合计").newNumber(0)
				.oldNumber(0).mainProjectNumber(0).cultivateProjectNumber(0).noncoreProjectNumber(0)
				.build());
		return init;
	}

	@Override
	public String export(Long baseInvestmentPlanId){

		String key = baseInvestmentPlanId + StringPool.DASH + UUID.randomUUID().toString().replace(StringPool.DASH, "");
		String fileName = key + ".xlsx";
		String exportPath = environment.getProperty("excel.path");

		/**
		 * 导出路径不存在则创建
		 */
		File file = new File(exportPath);
		if (!file.exists()) {
			file.mkdirs();
		}
		InputStream inputStream = this.getClass().getResourceAsStream("/exceldemo/investmentPlan.xlsx");
		ExcelWriter excelWriter = EasyExcel.write(exportPath + fileName).withTemplate(inputStream).build();

		// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
		// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
		// 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存

		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();

		BaseInvestmentPlan baseInvestmentPlan = getById(baseInvestmentPlanId);
		// 表一
		WriteSheet stakeWriteSheet = EasyExcel.writerSheet(0).build();
		List<StakeInvestmentPlan> stakeInvestmentPlans = stakeInvestmentPlanService.list(new LambdaQueryWrapper<StakeInvestmentPlan>()
				.eq(StakeInvestmentPlan::getBaseInvestmentPlanId, baseInvestmentPlanId));
		stakeInvestmentPlanService.write(stakeInvestmentPlans, excelWriter, stakeWriteSheet, fillConfig);

		// 表二
		List<FixedInvestmentPlan> fixedInvestmentPlans = fixedInvestmentPlanService.list(new LambdaQueryWrapper<FixedInvestmentPlan>()
				.eq(FixedInvestmentPlan::getBaseInvestmentPlanId, baseInvestmentPlanId));
		WriteSheet fixedWriteSheet = EasyExcel.writerSheet(1).build();
		fixedInvestmentPlanService.write(fixedInvestmentPlans, excelWriter, fixedWriteSheet, fillConfig);

		// 表三
		List<InvestmentPlanSummaryVO> investmentPlanSummaryVOS = summaryDetail(Integer.valueOf(baseInvestmentPlan.getFilingYear()), stakeInvestmentPlans, fixedInvestmentPlans);
		WriteSheet summaryWriteSheet = EasyExcel.writerSheet(2).build();
		write(investmentPlanSummaryVOS, excelWriter, summaryWriteSheet, fillConfig);

		BaseInvestmentPlanVO baseInvestmentPlanVO = baseInvestmentPlanWrapper.entityToVO(getById(baseInvestmentPlanId));
		// 其他参数可以使用Map封装
		Map<String, Object> otherMap = new HashMap<>(16);
		otherMap.put("filingUnitName", baseInvestmentPlanVO.getFilingUnitName());
		otherMap.put("filingYear", baseInvestmentPlanVO.getFilingYear());

		excelWriter.fill(otherMap, stakeWriteSheet);
		excelWriter.fill(otherMap, fixedWriteSheet);
		excelWriter.fill(otherMap, summaryWriteSheet);
		excelWriter.finish();
		String excelName = baseInvestmentPlanVO.getFilingYear() + "年项目投资计划_" +  baseInvestmentPlanVO.getFilingUnitName();
		fileNameMap.put(key, excelName);
		return key;
	}

	@Override
	public String exportImportFile(Long baseInvestmentPlanId) {
		String key = baseInvestmentPlanId + StringPool.DASH + UUID.randomUUID().toString().replace(StringPool.DASH, "");
		String fileName = key + ".xlsx";
		String exportPath = environment.getProperty("excel.path");

		/**
		 * 导出路径不存在则创建
		 */
		File file = new File(exportPath);
		if (!file.exists()) {
			file.mkdirs();
		}
		InputStream inputStream = this.getClass().getResourceAsStream("/exceldemo/investmentPlanExport.xlsx");
		ExcelWriter excelWriter = EasyExcel.write(exportPath + fileName).withTemplate(inputStream).build();

		// 这里注意 入参用了forceNewRow 代表在写入list的时候不管list下面有没有空行 都会创建一行，然后下面的数据往后移动。默认 是false，会直接使用下一行，如果没有则创建。
		// forceNewRow 如果设置了true,有个缺点 就是他会把所有的数据都放到内存了，所以慎用
		// 简单的说 如果你的模板有list,且list不是最后一行，下面还有数据需要填充 就必须设置 forceNewRow=true 但是这个就会把所有数据放到内存 会很耗内存

		FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
		// 表二
		WriteSheet baseWriteSheet = EasyExcel.writerSheet(1).build();
		BaseInvestmentPlanVO baseInvestmentPlanVO = baseInvestmentPlanWrapper.entityToVO(getById(baseInvestmentPlanId));
		// 其他参数可以使用Map封装
		Map<String, Object> baseMap = new HashMap<>(16);
		baseMap.put("filingUnitName", baseInvestmentPlanVO.getFilingUnitName());
		baseMap.put("filingYear", baseInvestmentPlanVO.getFilingYear());
		baseMap.put("filingDate", DateUtil.format(baseInvestmentPlanVO.getFilingDate(), DateUtil.PATTERN_DATE));

		baseMap.put("investmentScale", baseInvestmentPlanVO.getInvestmentScale().toPlainString());
		baseMap.put("fixedAssets", baseInvestmentPlanVO.getFixedAssets().toPlainString());
		baseMap.put("equityInvestment", baseInvestmentPlanVO.getEquityInvestment().toPlainString());
		baseMap.put("plannedInvestment", baseInvestmentPlanVO.getPlannedInvestment().toPlainString());
		baseMap.put("otherInvestment", baseInvestmentPlanVO.getOtherInvestment().toPlainString());
		baseMap.put("projectTotal", baseInvestmentPlanVO.getProjectTotal());
		baseMap.put("investmentDirection", baseInvestmentPlanVO.getInvestmentDirection());
		baseMap.put("investmentPurpose", baseInvestmentPlanVO.getInvestmentPurpose());


		excelWriter.fill(baseMap, baseWriteSheet);

		// 表三
		WriteSheet stakeWriteSheet = EasyExcel.writerSheet(2).build();
		List<StakeInvestmentPlan> stakeInvestmentPlans = stakeInvestmentPlanService.list(new LambdaQueryWrapper<StakeInvestmentPlan>()
				.eq(StakeInvestmentPlan::getBaseInvestmentPlanId, baseInvestmentPlanId));
		excelWriter.fill(new FillWrapper("stakeInvestmentPlans", stakeInvestmentPlanWrapper.entityToVO(stakeInvestmentPlans)), fillConfig, stakeWriteSheet);

		// 表四
		List<FixedInvestmentPlan> fixedInvestmentPlans = fixedInvestmentPlanService.list(new LambdaQueryWrapper<FixedInvestmentPlan>()
				.eq(FixedInvestmentPlan::getBaseInvestmentPlanId, baseInvestmentPlanId));
		WriteSheet fixedWriteSheet = EasyExcel.writerSheet(3).build();
		excelWriter.fill(new FillWrapper("fixedInvestmentPlans", fixedInvestmentPlanWrapper.entityToVO(fixedInvestmentPlans)), fillConfig, fixedWriteSheet);
		excelWriter.finish();
		String excelName = baseInvestmentPlanVO.getFilingYear() + "年_" + DateUtil.format(baseInvestmentPlanVO.getFilingDate(), DateUtil.PATTERN_DATE)
				+ "填报日_项目投资计划_" +  baseInvestmentPlanVO.getFilingUnitName();
		fileNameMap.put(key, excelName);
		return key;
	}

	@Override
	public void download(String key, HttpServletResponse response) {
		if (!fileNameMap.containsKey(key)){
			log.error("BaseInvestmentPlanServiceImpl 导出excel失败--------> key " + key);
			return;
		}
		String excelName = fileNameMap.get(key);
		String excelPath = environment.getProperty("excel.path") + StringPool.SLASH + key + ".xlsx";
		FileTools.exportExcel(excelPath, excelName, response);
		fileNameMap.remove(key);
	}

	/**
	 * 年度新增投资计划汇总表sheet页 数据写入
	 * @param investmentPlanSummaryVOS
	 * @param excelWriter
	 * @param writeSheet
	 * @param fillConfig
	 */
	private void write(List<InvestmentPlanSummaryVO> investmentPlanSummaryVOS, ExcelWriter excelWriter, WriteSheet writeSheet, FillConfig fillConfig){
		List<InvestmentPlanSummaryVO> oneList = new ArrayList<>();
		List<InvestmentPlanSummaryVO> twoList = new ArrayList<>();
		List<InvestmentPlanSummaryVO> threeList = new ArrayList<>();
		for (int i = 0; i<investmentPlanSummaryVOS.size(); i++){
			if(i >= 1 && i <= 3){
				oneList.add(investmentPlanSummaryVOS.get(i));
			}

			if(i >= 5 && i <= 7){
				twoList.add(investmentPlanSummaryVOS.get(i));
			}

			if(i >= 9 && i <= 15){
				threeList.add(investmentPlanSummaryVOS.get(i));
			}

		}
		excelWriter.fill(new FillWrapper("one", oneList), fillConfig, writeSheet);
		excelWriter.fill(new FillWrapper("two", twoList), fillConfig, writeSheet);
		excelWriter.fill(new FillWrapper("three", threeList), fillConfig, writeSheet);
	}

	@Override
	public void goBackToStash(String formId) {
		handleStatus(Long.valueOf(formId), UNREVIEWED, null);
	}

	@Override
	@Async("ttlExecutor")
	public Future<ImportResult> importExcel(String progressId, InputStream inputStream) {
		String progress = "progress";
		String key = progressId + "#half:hour";
		try {
			byte[] bytes = IOUtils.toByteArray(inputStream);
			inputStream = new ByteArrayInputStream(bytes);

			Map<String, Map<String,String>> mapRef= getRef();
			Map<String, ProjectInfo> projectMap = getProjectMap();

            List<Object> baseList = new ArrayList<>();
            EasyExcel.read(inputStream).build()
                    .read(EasyExcel.readSheet(1).headRowNumber(1).head(BaseInvestmentPlanImportExcelBean.class)
                            .registerReadListener(new PageReadListener<>(list -> baseList.addAll(list))).build());

			ImportResult baseResult = checkBaseData(mapRef, baseList);
			if (!baseResult.isSuccess()){
				CacheUtil.put(progress, progress, key, baseResult.getMsg());
				return new AsyncResult<>(baseResult);
			}

			inputStream.reset();
            List<Object> stakeList = new ArrayList<>();
            EasyExcel.read(inputStream).build()
                    .read(EasyExcel.readSheet(2).headRowNumber(3).head(StakeInvestmentPlanImportExcelBean.class)
                            .registerReadListener(new PageReadListener<>(list -> stakeList.addAll(list))).build());
			ImportExcelUtil.filterEmpty(stakeList);
			ImportResult stakeResult = checkStakeData(mapRef, projectMap, stakeList, progressId);
			if (!stakeResult.isSuccess()){
				CacheUtil.put(progress, progress, key, stakeResult.getMsg());
				return new AsyncResult<>(stakeResult);
			}

			inputStream.reset();
            List<Object> fixedList = new ArrayList<>();
            EasyExcel.read(inputStream).build()
                    .read(EasyExcel.readSheet(3).headRowNumber(3).head(FixedInvestmentPlanImportExcelBean.class)
                            .registerReadListener(new PageReadListener<>(list -> fixedList.addAll(list))).build());
			ImportExcelUtil.filterEmpty(fixedList);
			ImportResult fixedResult = checkFixedData(mapRef, projectMap, fixedList, progressId);
			if (!fixedResult.isSuccess()){
				CacheUtil.put(progress, progress, key, fixedResult.getMsg());
				return new AsyncResult<>(fixedResult);
			}

			// 主表信息
			BaseInvestmentPlan baseInvestmentPlan = (BaseInvestmentPlan) ImportExcelUtil.getEntityByExcelBean((BaseInvestmentPlanImportExcelBean) baseList.get(0), new BaseInvestmentPlan());


			int count = 0;
			int size = stakeList.size() + fixedList.size();
			List<StakeInvestmentPlan> stakeInvestmentPlanList=new ArrayList<>();
			List<FixedInvestmentPlan> fixedInvestmentPlanList=new ArrayList<>();
			// 年度新增股权投资计划数据
			for (Object readExcel : stakeList) {
				StakeInvestmentPlan stakeInvestmentPlan = (StakeInvestmentPlan) ImportExcelUtil.getEntityByExcelBean((StakeInvestmentPlanImportExcelBean)readExcel,new StakeInvestmentPlan());
				stakeInvestmentPlanList.add(stakeInvestmentPlan);
			}

			// 年度新增固定资产投资计划数据
			for (Object readExcel : fixedList) {
				FixedInvestmentPlan fixedInvestmentPlan = (FixedInvestmentPlan) ImportExcelUtil.getEntityByExcelBean((FixedInvestmentPlanImportExcelBean)readExcel,new FixedInvestmentPlan());
				fixedInvestmentPlanList.add(fixedInvestmentPlan);

			}
			StringBuilder msg=new StringBuilder();
			int year=Integer.parseInt(baseInvestmentPlan.getFilingYear());
//			msg.append(stakeInvestmentPlanService.checkMsg(stakeInvestmentPlanList,year));
//			msg.append(fixedInvestmentPlanService.checkMsg(fixedInvestmentPlanList,year));
			if(msg.length()>0){
				CacheUtil.put(progress, progress, key,msg);
				return new AsyncResult<>(new ImportResult(false,msg.toString()));
			}
			BaseInvestmentPlan old = getOldData(baseInvestmentPlan);
			if (Optional.ofNullable(old).isPresent()){
				//如果有老数据 则删除子表旧数据
				baseInvestmentPlan.setId(old.getId());
				stakeInvestmentPlanService.deleteByBaseId(old.getId());
				fixedInvestmentPlanService.deleteByBaseId(old.getId());
			}else {
				saveOrUpdate(baseInvestmentPlan);
			}
			for(StakeInvestmentPlan stakeInvestmentPlan:stakeInvestmentPlanList){
				//入库
				try {
					stakeInvestmentPlan.setBaseInvestmentPlanId(baseInvestmentPlan.getId());
					stakeInvestmentPlanService.saveOrUpdate(stakeInvestmentPlan);
					count++;
					int value = count * 100 / size;
					CacheUtil.put(progress, progress, key, value+100);
				} catch (Exception e) {
					log.error(stakeInvestmentPlan + "导入失败");
					CacheUtil.put(progress, progress, key,stakeInvestmentPlan + "导入失败");
					return new AsyncResult<>(new ImportResult(false,stakeInvestmentPlan + "导入失败"));
				}
			}

			for(FixedInvestmentPlan fixedInvestmentPlan:fixedInvestmentPlanList){
				//入库
				try {
					fixedInvestmentPlan.setBaseInvestmentPlanId(baseInvestmentPlan.getId());
					fixedInvestmentPlanService.saveOrUpdate(fixedInvestmentPlan);
					count++;
					int value = count * 100 / size;
					CacheUtil.put(progress, progress, key, value+100);
				} catch (Exception e) {
					log.error(fixedInvestmentPlan + "导入失败");
					CacheUtil.put(progress, progress, key,fixedInvestmentPlan + "导入失败");
					return new AsyncResult<>(new ImportResult(false,fixedInvestmentPlan + "导入失败"));
				}
			}

		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
			log.error("解析失败");
			CacheUtil.put(progress, progress, key,"解析失败");
			return new AsyncResult<>(new ImportResult(false,"解析失败"));
		}

		CacheUtil.put(progress, progress, key,"导入成功");
		return new AsyncResult<>(new ImportResult(true,"导入成功"));
	}

    @Override
    public void exportTemplateExcel(HttpServletResponse response, OutputStream os) {
        try {
            String fname = "投资计划导入模板";
            os = response.getOutputStream();//取得输出流
            response.reset();//清空输出流
            //下面是对中文文件名的处理
            response.setCharacterEncoding("UTF-8");//设置相应内容的编码格式
            InputStream inputStream = this.getClass().getResourceAsStream("/exceldemo/investmentPlanImport.xlsx");
            fname = java.net.URLEncoder.encode(fname, "UTF-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(fname.getBytes("UTF-8"), "UTF-8") + ".xlsx");

            response.setContentType("application/msexcel");//定义输出类型
            int len;
            byte[] b = new byte[2048];
            while ((len = inputStream.read(b)) != -1) {
                os.write(b, 0, len);
            }
            response.setHeader("Content-Length", String.valueOf(inputStream.available()));

            inputStream.close();
            os.close();
        }catch (Exception e){
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
    }

	@Override
	public ChartsVO statisticsCompany(BaseInvestmentPlanDTO baseInvestmentPlanDTO) {
		/**
		 * 填报年年度为空时默认为当前年度
		 */
		if (StringUtil.isBlank(baseInvestmentPlanDTO.getFilingYear())){
			baseInvestmentPlanDTO.setFilingYear(DateUtil.format(DateUtil.now(), DateUtil.PATTERN_YEAR));
		}
		List<InvestmentUnitSummaryVO> results = baseMapper.unitSummary(baseInvestmentPlanDTO.getFilingYear(), baseInvestmentPlanDTO.getFillingUnitIds());
		if (CollectionUtil.isEmpty(results)){
			return null;
		}

		List<String> data = new ArrayList<>();
		data.add("总计划投资额");
		data.add("股权投资计划");
		data.add("固定资产投资计划");
		LegendVO legendVO = LegendVO.builder().data(data).build();

		List<XAxisVO> xAxisVOS = new ArrayList<>();
		List<String> xList = new ArrayList<>();
		List<Object> planList = new ArrayList<>();
		List<Object> fixedList = new ArrayList<>();
		List<Object> stakeList = new ArrayList<>();
		List<String> ids = new ArrayList<>();

		BigDecimal endInvestment = new BigDecimal(0);
		BigDecimal endFixedInvestment = new BigDecimal(0);
		BigDecimal endStakeInvestment = new BigDecimal(0);
		for (InvestmentUnitSummaryVO result : results){
			if (StringUtil.isNotBlank(CheckName.getAbbreviationName(result.getUnitCheck()))){
				xList.add(CheckName.getAbbreviationName(result.getUnitCheck()));
			}else {
				xList.add(result.getUnitCheck());
			}
			if (baseInvestmentPlanDTO.getUnitType() != null && baseInvestmentPlanDTO.getUnitType() == 2){
				planList.add(result.getInvestment() != null ?
								BigDecimalUtil.divide(result.getInvestment(), new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) : 0);
				fixedList.add(result.getFixedInvestment() != null ?
								BigDecimalUtil.divide(result.getFixedInvestment(), new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) : 0);
				stakeList.add(result.getStakeInvestment() != null ?
								BigDecimalUtil.divide(result.getStakeInvestment(), new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) : 0);
			}else {
				planList.add(result.getInvestment() != null ? result.getInvestment() : 0);
				fixedList.add(result.getFixedInvestment() != null ? result.getFixedInvestment() : 0);
				stakeList.add(result.getStakeInvestment() != null ? result.getStakeInvestment() : 0);
			}

			ids.add(String.valueOf(result.getId()));
			endInvestment = BigDecimalUtil.add(endInvestment, result.getInvestment());
			endFixedInvestment = BigDecimalUtil.add(endFixedInvestment, result.getFixedInvestment());
			endStakeInvestment = BigDecimalUtil.add(endStakeInvestment, result.getStakeInvestment());
		}

		List<SeriesVO> seriesVOS = new ArrayList<>();
		seriesVOS.add(SeriesVO.builder().name("总计划投资额").type("bar").data(planList).build());
		seriesVOS.add(SeriesVO.builder().name("股权投资计划").type("bar").data(stakeList).build());
		seriesVOS.add(SeriesVO.builder().name("固定资产投资计划").type("bar").data(fixedList).build());

		xAxisVOS.add(XAxisVO.builder().data(xList).build());
		List<String> total = new ArrayList<>();
		total.add("总计划投资额: " + BigDecimalUtil.divide(endInvestment, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) + "亿元");
		total.add("总股权投资计划: " + BigDecimalUtil.divide(endFixedInvestment, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) + "亿元");
		total.add("总固定资产投资计划: " + BigDecimalUtil.divide(endStakeInvestment, new BigDecimal(10000), 2, BigDecimal.ROUND_HALF_UP) + "亿元");
		ChartsVO chartsVO = ChartsVO.builder().ids(ids).legend(legendVO)
				.xAxis(xAxisVOS).series(seriesVOS).total(total).build();
		return chartsVO;
	}

	private BaseInvestmentPlan getOldData(BaseInvestmentPlan baseInvestmentPlan){
		LambdaQueryWrapper<BaseInvestmentPlan> queryWrapper = new LambdaQueryWrapper<>();
		queryWrapper.eq(BaseInvestmentPlan::getFilingUnitId, baseInvestmentPlan.getFilingUnitId());
		queryWrapper.eq(BaseInvestmentPlan::getFilingYear, baseInvestmentPlan.getFilingYear());
		queryWrapper.eq(BaseInvestmentPlan::getFilingDate, DateUtil.format(baseInvestmentPlan.getFilingDate(), DateUtil.PATTERN_DATE));
		return getOne(queryWrapper);
	}

	private Map<String,Map<String,String>> getRef() {
		Map<String, Map<String, String>> mapRefs = new HashMap<>(16);
		mapRefs.put("projectNatureRef",baseInfoService.getChildMap(ValueSetConstant.PROJECT_NATURE));
		mapRefs.put("enterpriseRankRef",baseInfoService.getChildMap(ValueSetConstant.ENTERPRISE_RANK));

		Map<String,String> unitRef = new HashMap<>(16);
		try{
			List<PageData> allOrgs =  orgzationDao.list(null);
			if (CollectionUtil.isNotEmpty(allOrgs)){
				for (PageData pageData : allOrgs){
					unitRef.put((String)pageData.get("name"), (String)pageData.get("id"));
				}

			}
		}catch (Exception e){
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		mapRefs.put("unitRef",unitRef);


		return mapRefs;
	}

	private Map<String, ProjectInfo> getProjectMap(){
		List<ProjectInfo> projectInfos = projectInfoService.list(new LambdaQueryWrapper<ProjectInfo>().eq(ProjectInfo::getCreateCompanyId, TokenUtil.getTokenOrgId()));
		Map<String, ProjectInfo> map = new HashMap<>();
		if (CollectionUtil.isNotEmpty(projectInfos)){
			map = projectInfos.stream().collect(Collectors.toMap(ProjectInfo::getProjectName, a -> a,(k1,k2)->k1));
		}
		return map;
	}

	private ImportResult checkBaseData(Map<String,Map<String,String>> mapRef, List<Object> readExcels) {
		ImportResult importResult = new ImportResult(true,"");

		StringBuilder msg = new StringBuilder();

		if (CollectionUtil.isNotEmpty(readExcels)){
			int index = 2;
			BaseInvestmentPlanImportExcelBean excelBean = (BaseInvestmentPlanImportExcelBean) readExcels.get(0);

			//判空
			msg.append(ImportExcelUtil.checkEmpty("2", "填报单位", excelBean.getFilingUnitId(), index).getMsg());

			msg.append(ImportExcelUtil.checkEmpty("2", "填报年度", excelBean.getFilingYear(), index).getMsg());

			msg.append(ImportExcelUtil.checkEmpty("2", "填报时间", excelBean.getFilingDate(), index).getMsg());

			msg.append(ImportExcelUtil.checkEmpty("2", "投资规模", excelBean.getInvestmentScale(), index).getMsg());

			msg.append(ImportExcelUtil.checkEmpty("2", "其中：固定资产", excelBean.getFixedAssets(), index).getMsg());

			msg.append(ImportExcelUtil.checkEmpty("2", "其中：股权投资", excelBean.getEquityInvestment(), index).getMsg());

			msg.append(ImportExcelUtil.checkEmpty("2", "本年计划投资总额", excelBean.getPlannedInvestment(), index).getMsg());

			msg.append(ImportExcelUtil.checkEmpty("2", "其他投资金额", excelBean.getOtherInvestment(), index).getMsg());

			msg.append(ImportExcelUtil.checkEmpty("2", "投资项目总个数", excelBean.getProjectTotal(), index).getMsg());

			msg.append(ImportExcelUtil.checkEmpty("2", "投资主要方向", excelBean.getInvestmentDirection(), index).getMsg());
			msg.append(ImportExcelUtil.checkEmpty("2", "投资主要目的", excelBean.getInvestmentPurpose(), index).getMsg());


			//判断类型
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_INTEGER, "2", "填报年度",
					excelBean.getFilingYear(), index).getMsg());

			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_DATE, "2", "填报时间",
					excelBean.getFilingDate(), index).getMsg());

			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "2", "投资规模",
					excelBean.getInvestmentScale(), index).getMsg());

			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "2", "其中：固定资产",
					excelBean.getFixedAssets(), index).getMsg());

			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "2", "其中：股权投资",
					excelBean.getEquityInvestment(), index).getMsg());

			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "2", "本年计划投资总额",
					excelBean.getPlannedInvestment(), index).getMsg());

			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "2", "其他投资金额",
					excelBean.getOtherInvestment(), index).getMsg());

			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_INTEGER, "2", "投资项目总个数",
					excelBean.getProjectTotal(), index).getMsg());


			//判断完类型若有错直接返回
			if (msg.toString().length() > 0) {
				return new ImportResult(false, msg.toString());
			}

			//对象和字典是否存在校验
			//单位名称
			excelBean.setFilingUnitId(StringUtil.cleanChars(excelBean.getFilingUnitId()));
			if(mapRef.get("unitRef").containsKey(excelBean.getFilingUnitId())){
				String companyName = excelBean.getFilingUnitId();
				excelBean.setFilingUnitId(mapRef.get("unitRef").get(excelBean.getFilingUnitId()));
				if(!TokenUtil.getTokenOrgId().equals(excelBean.getFilingUnitId())){
					msg.append("sheet2第" + index + "行(填报单位=" + companyName + ")不是当前登录单位\n");
				}
			}else if(!StringUtil.isEmpty(excelBean.getFilingUnitId())){
				msg.append("sheet2第" + index + "行(填报单位=" + excelBean.getFilingUnitId() + ")在系统中不存在\n");
			}

			QueryWrapper<BaseInvestmentPlan> queryWrapper = new QueryWrapper<>();
			queryWrapper.eq("filing_unit_id", excelBean.getFilingUnitId());
			queryWrapper.eq("filing_year", excelBean.getFilingYear());
			queryWrapper.eq("filing_date", excelBean.getFilingDate());
			queryWrapper.ne("status", FormStatusConstant.UNREVIEWED);
			if (Optional.ofNullable(getOne(queryWrapper)).isPresent()){
				msg.append("sheet2该年度数据 该填报时间已上报\n");
			}

		}else {
			msg.append("sheet2数据未填写\n");
		}

		//统一放置报错
		if (msg.toString().length()>0) {
			importResult = new ImportResult(false, msg.toString());
		}
		return importResult;

	}

	private ImportResult checkStakeData(Map<String,Map<String,String>> mapRef, Map<String, ProjectInfo> projectMap, List<Object> readExcels, String progressId) {

		ImportResult importResult = new ImportResult(true,"");

		StringBuilder msg = new StringBuilder();
		for (Object readExcel : readExcels) {
			StakeInvestmentPlanImportExcelBean excelBean = (StakeInvestmentPlanImportExcelBean)readExcel;
			int index = readExcels.indexOf(readExcel);

			//判空
			msg.append(ImportExcelUtil.checkEmpty("3", "项目名称",
					excelBean.getProjectName(), index).getMsg());
			msg.append(ImportExcelUtil.checkEmpty("3", "项目性质",
					excelBean.getProjectNatureId(), index).getMsg());
			msg.append(ImportExcelUtil.checkEmpty("3", "项目分类",
					excelBean.getProjectCategory(), index).getMsg());
			msg.append(ImportExcelUtil.checkEmpty("3", "投资企业 名称",
					excelBean.getInvestmentCompanyId(), index).getMsg());
			msg.append(ImportExcelUtil.checkEmpty("3", "是否本年新增项目",
					excelBean.getIsNewProject(), index).getMsg());
//			msg.append(ImportExcelUtil.checkEmpty("3", "投资企业 层级(集团为一级）",
//					excelBean.getInvestmentCompanyRankId(), index).getMsg());

			//判断类型
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_INTEGER, "3", "项目分类",
					excelBean.getProjectCategory(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "3", "年初被投资企业注册资本 总额",
					excelBean.getBeginningInvestedTotal(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "3", "年初被投资企业注册资本 其中：本企业",
					excelBean.getBeginningInvestedEnterprise(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "3", "年初被投资企业注册资本 年初持股比例（%)",
					excelBean.getBeginningInvestedStake(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "3", "项目计划总投资 总额",
					excelBean.getPlanTotalInvestment(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "3", "项目计划总投资 其中：本企业",
					excelBean.getPlanTotalInvestmentEnterprise(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "3", "项目计划总投资 内部收益率",
					excelBean.getPlanTotalInvestmentIrr(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "3", "本年计划完成投资 投资额",
					excelBean.getPlanCompleteInvestment(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "3", "本年计划完成投资 本年投资完成后，累计完成投资总额",
					excelBean.getPlanCompleteInvestmentTotal(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "3", "本年计划完成投资 年末预计持股比例（%）",
					excelBean.getPlanCompleteInvestmentStake(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_INTEGER, "3", "是否本年新增项目",
					excelBean.getIsNewProject(), index).getMsg());
		}
		//判断完类型若有错直接返回
		if (msg.toString().length() > 0) {
			return new ImportResult(false, msg.toString());
		}

		//对象和字典是否存在校验
		int size=readExcels.size();
		int count=0;
		for (Object readExcel : readExcels) {
			StakeInvestmentPlanImportExcelBean excelBean = (StakeInvestmentPlanImportExcelBean) readExcel;
			int index = readExcels.indexOf(readExcel);
			//单位名称
//			if(mapRef.get("unitRef").containsKey(excelBean.getInvestmentCompanyId())){
//				excelBean.setInvestmentCompanyId(mapRef.get("unitRef").get(excelBean.getInvestmentCompanyId()));
//			}else if(!StringUtil.isEmpty(excelBean.getInvestmentCompanyId())){
//				msg.append("sheet3第" + index + "行(投资企业 名称=" + excelBean.getInvestmentCompanyId() + ")在系统中不存在\n");
//			}

			//项目分类
			if (!StringUtil.isEmpty(excelBean.getProjectCategory())){
				if (!("1".equals(excelBean.getProjectCategory()) || "2".equals(excelBean.getProjectCategory())
						|| "3".equals(excelBean.getProjectCategory()) || "4".equals(excelBean.getProjectCategory()))){
					msg.append("sheet3第"+index+"行(项目分类="+excelBean.getProjectCategory()+")错误\n");
				}
			}

			//是否本年新增项目
			if (!StringUtil.isEmpty(excelBean.getIsNewProject())){
				if (!("1".equals(excelBean.getIsNewProject()) || "2".equals(excelBean.getIsNewProject()))){
					msg.append("sheet3第"+index+"行(是否本年新增项目="+excelBean.getIsNewProject()+")错误\n");
				}
			}

			//项目性质
			if (StringUtil.isNotBlank(excelBean.getProjectNatureId())){
				if (!mapRef.get("projectNatureRef").containsKey(excelBean.getProjectNatureId())) {
					msg.append("sheet3第"+index+"行(项目性质=" + excelBean.getProjectNatureId() + ")在系统中不存在\n");
				}
			}

			//层级(集团为一级）
			if (StringUtil.isNotBlank(excelBean.getInvestmentCompanyRankId())){
				if (!mapRef.get("enterpriseRankRef").containsKey(excelBean.getInvestmentCompanyRankId())) {
					msg.append("sheet3第"+index+"行(投资企业 层级(集团为一级）=" + excelBean.getInvestmentCompanyRankId() + ")在系统中不存在\n");
				}
			}

			//项目名称
			if(projectMap.containsKey(excelBean.getProjectName())){
				excelBean.setProjectId(projectMap.get(excelBean.getProjectName()).getId());
				excelBean.setCapital(projectMap.get(excelBean.getProjectName()).getCapital());
				excelBean.setIsNegativeProject(projectMap.get(excelBean.getProjectName()).getIsNegativeProject());
			}else if(!StringUtil.isEmpty(excelBean.getProjectName())){
				msg.append("sheet3第" + index + "行(项目名称=" + excelBean.getProjectName() + ")在系统中不存在\n");
			}

			count++;
			int value = count * 100 / size;
			CacheUtil.put("progress","progress",progressId, value);
		}

		//统一放置报错
		if (msg.toString().length()>0) {
			importResult = new ImportResult(false, msg.toString());
		}
		return importResult;
	}

	private ImportResult checkFixedData(Map<String,Map<String,String>> mapRef, Map<String, ProjectInfo> projectMap,  List<Object> readExcels, String progressId) {

		ImportResult importResult = new ImportResult(true,"");

		StringBuilder msg = new StringBuilder();
		for (Object readExcel : readExcels) {
			FixedInvestmentPlanImportExcelBean excelBean = (FixedInvestmentPlanImportExcelBean)readExcel;
			int index = readExcels.indexOf(readExcel);

			//判空
			msg.append(ImportExcelUtil.checkEmpty("4", "项目名称",
					excelBean.getProjectName(), index).getMsg());
			msg.append(ImportExcelUtil.checkEmpty("4", "项目性质",
					excelBean.getProjectNatureId(), index).getMsg());
			msg.append(ImportExcelUtil.checkEmpty("4", "项目分类",
					excelBean.getProjectCategory(), index).getMsg());
			msg.append(ImportExcelUtil.checkEmpty("4", "投资企业 名称",
					excelBean.getInvestmentCompanyId(), index).getMsg());
//			msg.append(ImportExcelUtil.checkEmpty("4", "投资企业 层级(集团为一级）",
//					excelBean.getInvestmentCompanyRankId(), index).getMsg());
//			msg.append(ImportExcelUtil.checkEmpty("4", "本年度投资计划 工程主要部位形象进度",
//					excelBean.getPlanInvestmentProgress(), index).getMsg());
			msg.append(ImportExcelUtil.checkEmpty("4", "是否新开工项目",
					excelBean.getIsNewProject(), index).getMsg());

			//判断类型
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_INTEGER, "4", "项目分类",
					excelBean.getProjectCategory(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "4", "计划 总投资",
					excelBean.getPlanTotalInvestment(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "4", "内部 收益率",
					excelBean.getIrr(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_INTEGER, "4", "是否本年新增项目",
					excelBean.getIsNewProject(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "4", " 已完成投资 其中：上年度实际投资",
					excelBean.getCompleteInvestmentLastYear(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "4", "已完成投资 累计总额",
					excelBean.getCompleteInvestmentTotal(), index).getMsg());
			msg.append(ImportExcelUtil.checkType(ImportExcelUtil.TYPE_BIGDECIMAL, "4", "本年度投资计划 投资额",
					excelBean.getPlanInvestmentTotal(), index).getMsg());

		}
		//判断完类型若有错直接返回
		if (msg.toString().length() > 0) {
			return new ImportResult(false, msg.toString());
		}

		//对象和字典是否存在校验
		List<String> parentNameList = new ArrayList<>();
		int size=readExcels.size();
		int count=0;
		for (Object readExcel : readExcels) {
			FixedInvestmentPlanImportExcelBean excelBean = (FixedInvestmentPlanImportExcelBean) readExcel;
			int index = readExcels.indexOf(readExcel);
			//单位名称
//			if(mapRef.get("unitRef").containsKey(excelBean.getInvestmentCompanyId())){
//				excelBean.setInvestmentCompanyId(mapRef.get("unitRef").get(excelBean.getInvestmentCompanyId()));
//			}else if(!StringUtil.isEmpty(excelBean.getInvestmentCompanyId())){
//				msg.append("sheet4第" + index + "行(投资企业 名称=" + excelBean.getInvestmentCompanyId() + ")在系统中不存在\n");
//			}

			//项目分类
			if (!StringUtil.isEmpty(excelBean.getProjectCategory())){
				if (!("1".equals(excelBean.getProjectCategory()) || "2".equals(excelBean.getProjectCategory())
						|| "3".equals(excelBean.getProjectCategory()) || "4".equals(excelBean.getProjectCategory()))){
					msg.append("sheet4第"+index+"行(项目分类="+excelBean.getProjectCategory()+")错误\n");
				}
			}

			//是否本年新增项目
			if (!StringUtil.isEmpty(excelBean.getIsNewProject())){
				if (!("1".equals(excelBean.getIsNewProject()) || "2".equals(excelBean.getIsNewProject()))){
					msg.append("sheet4第"+index+"行(是否本年新增项目="+excelBean.getIsNewProject()+")错误\n");
				}
			}

			//项目性质
			if (StringUtil.isNotBlank(excelBean.getProjectNatureId())){
				if (!mapRef.get("projectNatureRef").containsKey(excelBean.getProjectNatureId())) {
					msg.append("sheet4第"+index+"行(项目性质=" + excelBean.getProjectNatureId() + ")在系统中不存在\n");
				}
			}

			//层级(集团为一级）
			if (StringUtil.isNotBlank(excelBean.getInvestmentCompanyRankId())){
				if (!mapRef.get("enterpriseRankRef").containsKey(excelBean.getInvestmentCompanyRankId())) {
					msg.append("sheet4第"+index+"行(投资企业 层级(集团为一级）=" + excelBean.getInvestmentCompanyRankId() + ")在系统中不存在\n");
				}
			}

			//项目名称
			if(projectMap.containsKey(excelBean.getProjectName())){
				excelBean.setProjectId(projectMap.get(excelBean.getProjectName()).getId());
				excelBean.setCapital(projectMap.get(excelBean.getProjectName()).getCapital());
				excelBean.setIsNegativeProject(projectMap.get(excelBean.getProjectName()).getIsNegativeProject());
			}else if(!StringUtil.isEmpty(excelBean.getProjectName())){
				msg.append("sheet4第" + index + "行(项目名称=" + excelBean.getProjectName() + ")在系统中不存在\n");
			}

			count++;
			int value = count * 100 / size;
			CacheUtil.put("progress","progress",progressId, value);
		}

		//统一放置报错
		if (msg.toString().length()>0) {
			importResult = new ImportResult(false, msg.toString());
		}
		return importResult;
	}


	@Override
	public List<PageData> findInvestListByDateCreate(PropertyTime propertyTime){
		List<PageData> listByDateRange = new ArrayList<>();
		try {
			PageData pageData = new PageData();
			pageData.put("startTime",propertyTime.getStartTime());
			pageData.put("endTime",propertyTime.getEndTime());
			List<PageData> pageDataList = fixedInvestmentPlanMapper.findInvestByCreate(pageData);
			listByDateRange = pageDataList;
		} catch (Exception e) {
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		return listByDateRange;
	}

	@Override
	public String saveInvestmentPlan(String data){
		YthResult ythResult = new YthResult();
		//成功的id集合
		List<String> successIds = new ArrayList<>();
		//失败的id集合
		List<String> failIds = new ArrayList<>();
		//失败的原因
		List<String> failReasons = new ArrayList<>();
		//将json字符串转换成list
		List<BaseInvestmentPlan> dataList = JSON.parseArray(data, BaseInvestmentPlan.class);
		if (CollectionUtil.isNotEmpty(dataList)){
			//组织map
			Map<String, String> orgSourceMap = orgService.getSourceId();
			//根据datasourceIds 查询出所有的数据
			List<BaseInvestmentPlan> list = list(new LambdaQueryWrapper<BaseInvestmentPlan>().in(BaseInvestmentPlan::getDataSourceId, dataList.stream().map(BaseInvestmentPlan::getDataSourceId).toArray()));
			if (CollectionUtil.isNotEmpty(list)){
				//删除子集
				List<Long> ids = list.stream().map(BaseInvestmentPlan::getId).collect(Collectors.toList());
				fixedInvestmentPlanService.remove(new LambdaQueryWrapper<FixedInvestmentPlan>().in(FixedInvestmentPlan::getBaseInvestmentPlanId, ids));
				stakeInvestmentPlanService.remove(new LambdaQueryWrapper<StakeInvestmentPlan>().in(StakeInvestmentPlan::getBaseInvestmentPlanId, ids));
			}
			//如果数据库中有数据，就更新，没有就新增
			for (BaseInvestmentPlan entity:dataList){
				transfer(entity,orgSourceMap);
				//id重复略过
				if (CollectionUtil.isNotEmpty(list)){
					List<String> olIds = list.stream().map(BaseInvestmentPlan::getDataSourceId).collect(Collectors.toList());
					String dataSourceId = entity.getDataSourceId();
					//判断数据库中是否有数据
					if (olIds.contains(dataSourceId)){
						for (BaseInvestmentPlan oldEntity:list){
							if (dataSourceId.equals(oldEntity.getDataSourceId())){
								//判断status是否为0，如果是0，就更新，不是0，就不更新
								if (CheckStatus.checkCode(oldEntity.getStatus())){
									successIds.add(dataSourceId);
									entity.setId(oldEntity.getId());
									entity.setDataSource(YthConstant.DATA_NINGBO);
									submit(entity);
									list.remove(oldEntity);
									break;
								}else {
									failIds.add(dataSourceId);
									failReasons.add("dataSourceId:"+dataSourceId+"数据已提交且已经在流程中，无法更新");
									break;
								}
							}
						}
					}else {
						//如果数据库中没有数据，就新增
						entity.setDataSource(YthConstant.DATA_NINGBO);
						submit(entity);
						successIds.add(entity.getDataSourceId());
					}
				}else {
					//如果数据库中没有数据，就新增
					entity.setDataSource(YthConstant.DATA_NINGBO);
					submit(entity);
					successIds.add(entity.getDataSourceId());
				}
			}
		} else {
			failReasons.add("数据为空");
		}
		ythResult.setSuccessIds(successIds);
		ythResult.setFailIds(failIds);
		ythResult.setFailReason(StringUtils.join(failReasons, ";"));
		//ythResult转换成json字符串
		return JSON.toJSONString(ythResult);
	}

	private void transfer(BaseInvestmentPlan entity, Map<String, String> orgSourceMap){
		Optional.ofNullable(entity.getFilingUnitId()).ifPresent(m ->
				{
					String orgId = orgSourceMap.get(m);
					if (StringUtil.isNotBlank(orgId)){
						entity.setFilingUnitId(orgId);
						entity.setCreateCompanyId(orgId);
					}
				}
		);
	}


}
